/* 
 * 版本信息
 * Version 1.0.1
 * 
 *  实现功能
 *  所有事件阻止冒泡函数返回false
 *  两种风格（1,checkbox;2,default） 
 *  一、单击左侧+ -  展开,收起     open close
 *     1、展开事件 
 *          beforeopen(fn beforeopen_callback)
 *          open(fn open_callback )
 *          afteropen(fn afteropen_callback)
 *     2、收起事件
 *          beforeClose(fn beforeclose_callback)
 *          close(fn close_callback)
 * 			afterclose(fn afterclose_callback)
 *  二、单击节点  check   
 *      A、 default  
 * 			1、beforecheck()
 * 			2、check()
 * 			3、aftercheck()
 * 		B、checkbox 
 * 			1、beforecheck()
 * 			2、check()
 * 			3、aftercheck()
 *  提供的方法
 *      1、设置节点的check属性  
 * 		2、设置节点的open close属性
 *      3、获取节点对象
 * 		4、获取节点的父节点
 * 		5、获取节点的子节点
 * 		6、获取所有select节点
 * 		7、展开某节点下的所有节点
 *   
 */
(function(jQuery) {

	//样式名称
	var className = {
		div : "tree",
		li_open : "tree-open",
		ins_open : "tree-icon-open",
		ins_close : "tree-icon-close",
		ins_leaf : "tree-icon-leaf",
		li_close : "tree-close",
		leaf : "tree-leaf",
		last : "tree-last",
		checked : "tree-checked",
		unchecked : "tree-unchecked",
		undetermined : "tree-undetermined",
		open : "open",
		uncheckbox_checked : "tree-uncheckbox-checked"
	}

	//初始化tree innerHtml
	function init($this, options) {
		jQuery($this).empty().removeClass().addClass(className.div + "-" + options.tree_themes).addClass(
				options.tree_checkbox);
		var $ul = jQuery($this).append("<ul></ul>").find("ul");
		var ulInnerHtml = "";
		if (!options.tree_data) {
			return;
		}
		jQuery.each(options.tree_data, function(index, entry) {
			ulInnerHtml += getNodeStr("", entry, options.tree_checkbox, options.tree_data.length == (index + 1));
		})
		$ul.append(ulInnerHtml);
		$ul.find("a").attr("href", "javascript:void(0);");
	}

	//节点展开
	function liopen($li) {

		$li.removeClass(className.li_close).addClass(className.li_open).children("ul").show();

		$li.children("a").children("ins:last").removeClass(className.ins_close).addClass(className.ins_open);

	}
	//节点关闭
	function liclose($li) {

		$li.removeClass(className.li_open).addClass(className.li_close).children("ul").hide();
		$li.children("a").children("ins:last").removeClass(className.ins_open).addClass(className.ins_close);

	}
	//绑定事件
	function initEvent($this, options) {
		$this.find("li").die("click");
		$this.find("a").die("click");
		//展开闭合
		$this.find("li").live("click", function(event) {
			$_this = jQuery(this);
			if (!$_this.hasClass(className.leaf)) {
				//展开
				if ($_this.hasClass(className.li_close)) {
					if (options.tree_callback.beforeopen($_this) == false) {
						return false;
					}

					liopen($_this);

					options.tree_callback.open($_this);

					options.tree_callback.afteropen($_this);

				} else {
					//闭合
				if (options.tree_callback.beforeclose($_this) == false) {
					return false;
				}
				liclose($_this);
				if (options.tree_callback.close($_this) != false) {

					return options.tree_callback.afterclose($_this);
				}
			}
		}
		return false;
	}	);
		//选中
		$this.find("a").live("click", function(event) {
			var $li = jQuery(this).parent();
			if (options.tree_callback.beforecheck($li) == false) {
				return false;
			}
			if (options.tree_checkbox === "checkbox") {

				//checkbox情况

				//取消选中
				if ($li.hasClass(className.checked)) {
					checkboxUnchecked($li);

				} else {
					checkboxChecked($li);

				}

				flushLiChecked($li);
				if (options.tree_callback.check($li) != false) {
					options.tree_callback.aftercheck($li);
				}
				return false;
			}

			//无checkbox

			$this.find("li").removeClass(className.uncheckbox_checked);

			$li.addClass(className.uncheckbox_checked);
			if (options.tree_callback.check($li) != false) {
				options.tree_callback.aftercheck($li);
			}
			return false;
		});
	}
	//checkbox模式 取消选中
	function checkboxUnchecked($li) {
		$li.removeClass(className.checked + " " + className.undetermined).addClass(className.unchecked).find("li")
				.removeClass(className.checked + " " + className.undetermined).addClass(className.unchecked);
	}
	//checkbox模式 选中
	function checkboxChecked($li) {
		$li.removeClass(className.unchecked + " " + className.undetermined).addClass(className.checked).find("li")
				.removeClass(className.unchecked + " " + className.undetermined).addClass(className.checked);
	}
	//刷新树的节点的选中状态(级联父节点)
	function flushLiChecked($li) {
		var $supLi = $li.parent().parent();
		if (!$supLi.is("li")) {
			return;
		}
		//全选
		var flagChecked = $li.siblings("." + className.unchecked).length == 0
				&& $li.siblings("." + className.undetermined).length == 0 && $li.hasClass(className.checked);

		//全不选
		var flagUnchecked = $li.siblings("." + className.checked).length == 0
				&& $li.siblings("." + className.undetermined).length == 0 && $li.hasClass(className.unchecked);
		//全不选
		if (flagUnchecked) {
			$supLi.removeClass(className.checked + " " + className.undetermined).addClass(className.unchecked);
			flushLiChecked($supLi);
			return;
		}
		//全选
		if (flagChecked) {
			$supLi.removeClass(className.unchecked + " " + className.undetermined).addClass(className.checked);
			flushLiChecked($supLi);
			return;
		}

		//半选
		$supLi.removeClass(className.unchecked).removeClass(className.checked).addClass(className.undetermined);
		flushLiChecked($supLi);
		return;

	}

	//获取节点参数innerHtml
	function getAttrStr(attr) {
		var str = "";

		jQuery.each(attr, function(index, entry) {
			str += (' ' + entry.key + '=' + '"' + entry.value + '"');
		});
		return str;
	}
	//获取节点innerHtml
	function getNodeStr(str, initInfo, tree_checkbox, last) {
		var children = initInfo.children;

		var leaf = !(Object.prototype.toString.apply(children) === '[object Array]') || children.length == 0;
		var strTemp = '<li ' + getAttrStr(initInfo.attr) + 'id="' + initInfo.id + '" class="'
				+ (last ? (className.last + " ") : "") + (leaf ? (className.leaf + " ") : (className.li_open + " "))
				+ (tree_checkbox == "checkbox" ? className.unchecked : '')
				+ '"> <ins class="tree-icon">&nbsp;</ins> <a href="#">'
				+ (tree_checkbox == "checkbox" ? ' <ins class="tree-checkbox">&nbsp;</ins>' : '') + ' <ins class="'
				+ (leaf ? className.ins_leaf : className.ins_open) + '">&nbsp;</ins> ' + initInfo.title + '</a>';

		//退出递归
		if (leaf) {
			return strTemp + '</li>';
		}
		strTemp += "<ul>";
		jQuery.each(children, function(index, entry) {

			strTemp += getNodeStr(str, entry, tree_checkbox, index == children.length - 1);

		});
		strTemp += "</ul>";
		return strTemp + '</li>';
	}

	//初始化tree
	jQuery.fn.tree = function(options) {
		var callback = jQuery.extend( {}, jQuery.fn.tree.defaults.tree_callback, options.tree_callback);
		var options = jQuery.extend( {}, jQuery.fn.tree.defaults, options);

		options.tree_callback = callback;

		var basePath = "";
		jQuery.each(jQuery("script"), function(index, entry) {
			if (entry.src && entry.src.match(/plugin\/zsTree\/com.zs.plugin.tree\.js$/)) {
				basePath = entry.src.replace(/plugin\/zsTree\/com.zs.plugin.tree\.js$/, '');
				return false;
			}
		});

		jQuery("head").append(
				'<link href="' + basePath + 'plugin/zsTree/themes/' + options.tree_themes
						+ '/style.css" rel="stylesheet" type="text/css" />');
		return this.each(function() {
			init(this, options);
			initEvent(jQuery(this), options);
		});
	}

	//获取节点
	jQuery.fn.getNode = function($li) {

		if (jQuery($li).isChildOf(jQuery(this).selector)) {
			return jQuery($li);
		}

		return jQuery( []);

	};
	//设置节点是否被选中
	jQuery.fn.checkNode = function($li, flag) {
		var checkboxModel = jQuery(this).hasClass("checkbox");
		$li = jQuery(this).getNode($li);
		if (!checkboxModel) {
			$li.removeClass(className.uncheckbox_checked);
			if (flag) {
				$li.addClass(className.uncheckbox_checked);
			}
			return this;
		}

		$li.removeClass(className.unchecked + " " + className.undetermined + " " + className.checked);

		if (flag) {
			checkboxChecked($li);
		} else {
			checkboxUnchecked($li);
		}
		flushLiChecked($li)
		return this;
	};

	//设置节点是否展开
	jQuery.fn.openNode = function($li, flag) {
		$li = jQuery(this).getNode($li);
		return this.each(function() {
			if (flag) {
				liopen($li);
				return;
			}
			liclose($li);
		});
	};

	// 获取展开的节点

	jQuery.fn.getOpenedNodes = function() {
		var result = [];
		this.each(function() {

			var openedNodes = jQuery(this).find("li[class*='" + className.li_open + "']");
			jQuery.each(openedNodes, function(index, entry) {
				result.push(entry);
			})
		});

		jQuery.unique(result);

		return jQuery(result);
	};
	//获取节点的父节点
	jQuery.fn.getParentNode = function($li) {
		$li = jQuery(this).getNode($li);
		return $li.parent().parent().is("li") ? $li.parent().parent() : jQuery(this);
	};

	//获取节点的子节点
	jQuery.fn.getChildrenNode = function($li) {
		return jQuery(this).getNode($li).children("ul").children("li");
	};

	//获取所有被选中的节点
	jQuery.fn.getCheckedNodes = function() {

		var result = [];

		this.each(function() {
			var checkedNodes = jQuery(this).hasClass("checkbox") ? (jQuery(this).find("li[class*='" + className.checked
					+ "']")) : (jQuery(this).find("." + className.uncheckbox_checked));

			jQuery.each(checkedNodes, function(index, entry) {
				result.push(entry);
			});
		});

		jQuery.unique(result);

		return jQuery(result);
	};

	//判断当前节点是否是传入节点的子节点
	jQuery.fn.isChildOf = function(selector) {
		if (!typeof (selector) == "string") {
			selector = jQuery(selector).selector;
		}
		return (this.parents(selector).length > 0);
	};

	//基本设置
	jQuery.fn.tree.defaults = {
		tree_themes : "default",
		tree_checkbox : "",
		tree_callback : {
			beforeopen : jQuery.noop,
			open : jQuery.noop,
			afteropen : jQuery.noop,
			beforecheck : jQuery.noop,
			check : jQuery.noop,
			aftercheck : jQuery.noop,
			beforeclose : jQuery.noop,
			close : jQuery.noop,
			afterclose : jQuery.noop,
			beforeclick : jQuery.noop,
			click : jQuery.noop,
			afterclick : jQuery.noop
		}
	};

})(jQuery);
